App.require(function () {
    var app = App.getCurrent();

    app.definePage("strdatetimePickerActive", {
        getDomObj: function () {
            this.attachDom("#previous", "previous")
                .attachDom("#next", "next")
                .attachDom(".select-main-container", "mainContainer")
                .attachDom(".month-container", "monthContainer")
                .attachDom(".select-month-container", "selectContainer")
                .attachDom(".year-month", "yearMonth")
                .attachDom(".year-container", "yearContainer")
                .attachDom(".select-date-container", "header")
                .attachEvent("yearMonth", "click", this.selectMonthHandler, false)
                .attachEvent("previous", "iconclick", this.previousHandler, false)
                .attachEvent("monthContainer", "touchstart", this.touchstartMonthHandler, false)
                .attachEvent("monthContainer", "touchmove", this.touchmoveMonthHandler, false)
                .attachEvent("monthContainer", "touchend", this.touchendMonthHandler, false)
                .attachEvent("yearContainer", "click", this.selectYearHandler, false)
                .attachEvent("yearContainer", "touchstart", this.touchstartYearHandler, false)
                .attachEvent("yearContainer", "touchmove", this.touchmoveYearHandler, false)
                .attachEvent("yearContainer", "touchend", this.touchendYearHandler, false)
                .attachEvent("monthContainer", "click", this.selectDayHandler, false)
                .attachEvent("selectContainer", "animationend", this.animationEndHandler, false)
                .attachEvent("next", "iconclick", this.nextHandler, false);
        },
        selectTime: function () {
            this.parent.render("strdatetimePickerTime", true);
        },
        touchstartMonthHandler: function (ev) {
            if (ev.touches.length > 1) return;
            var touch = ev.touches[0];
            this.data.startX = touch.clientX;
            this.data.touchTime = Date.now();
        },
        touchmoveMonthHandler: function (ev) {
            ev.preventDefault();
            ev.stopPropagation();
            if (ev.touches.length > 1) return;
        },
        touchendMonthHandler: function (ev) {
            if (ev.touches.length > 1) return;
            var touch = ev.changedTouches[0], touchX = touch.clientX, touchTime = Date.now();
            var speed = (touchX - this.data.startX) / (touchTime - this.data.touchTime) * 1000;
            if (speed > 100) {
                this.previousHandler();
            }
            else if (speed < -100) {
                this.nextHandler();
            }
        },
        touchstartYearHandler: function (ev) {
            var touches = ev.touches;
            if (touches.length > 1) return;
            var touch = touches[0];
            this.data.startY = touch.clientY;
            this.data.startTime = Date.now();
        },
        _computedYearItemHtml: function (i, year) {
            var data = this.data, minDate = data.minDate, maxDate = data.maxDate;
            var classStyle = i === year ? "selected" : "";
            if (minDate || maxDate) {
                if (!minDate) {
                    if (maxDate.year < i) {
                        classStyle += " str-disabled-date-item"
                    }
                }
                if (!maxDate) {
                    if (minDate.year > i) {
                        classStyle += " str-disabled-date-item"
                    }
                }
                if (minDate && maxDate) {
                    if (minDate.year > i || maxDate.year < i) {
                        classStyle += " str-disabled-date-item"
                    }
                }
            }
            
            return "<li><span class='" + classStyle.trim() + "'>" + i + "</span></li>";
        },
        changeYearContainer: function (deltaY) {
            var transformY = this.data.transformY - deltaY, 
                yearContainer = this.domList.yearContainer, 
                ul = yearContainer.firstElementChild;
            
            if (transformY > 0) {
                transformY -= 52;
                this.data.startY += 52;
                this.data.start -= 3;
                this.data.end -= 3;
                var html = "", year = this.data.yDate.year;
                for (var i = this.data.start; i <= this.data.start + 2; i++) {
                    html += this._computedYearItemHtml(i, year);
                }
                
                ul.insertAdjacentHTML("afterbegin", html);
                for (var i = 0; i < 3; i++) {
                    ul.removeChild(ul.lastElementChild);
                }
            }
            else if (transformY < -104) {
                transformY += 52;
                this.data.startY -= 52;
                this.data.start += 3;
                var html = "", year = this.data.yDate.year;
                for (var i = this.data.end; i <= this.data.end + 2; i++) {
                    html += this._computedYearItemHtml(i, year);
                }
                ul.insertAdjacentHTML("beforeend", html);
                for (var i = 0; i < 3; i++) {
                    ul.removeChild(ul.firstElementChild);
                }
                this.data.end += 3;
            }
            yearContainer.style.transform = "translateY(" + transformY + "px)";
            
            this.data.backTransformY = transformY;
        },
        touchmoveYearHandler: function (ev) {
            ev.preventDefault();
            ev.stopPropagation();
            var touches = ev.touches;
            if (touches.length > 1) return;
            var moveY = touches[0].clientY;
            var deltaY = this.data.startY - moveY;
            this.changeYearContainer(deltaY);
        },
        touchendYearHandler: function (ev) {
            var touches = ev.changedTouches;
            if (touches.length > 1) return;
            var touch = touches[0];
            var speed = (-touch.clientY + this.data.startY) * 100 / (Date.now() - this.data.startTime);
            var animation = new Animation(10, 0, Animation.normal);
            var that = this, total = 0;
            this.data.transformY = this.data.backTransformY;
            animation.onUpdate(function () {
                speed = parseInt(0.8 * speed);
                var s = Math.abs(speed) == speed ? 1 : -1;
                var distance = Math.abs(speed) > 0 ? s * 10 : s * speed;
                total += distance;
                
                if (Math.abs(speed) < 10) {
                    this.ended = true;
                    that.data.transformY = that.data.backTransformY;
                }
                else {
                    var transformY = that.data.transformY - total, 
                        yearContainer = that.domList.yearContainer, 
                        ul = yearContainer.firstElementChild;

                    if (transformY > 0) {
                        transformY -= 52;
                        total += 52;
                        that.data.startY += 52;
                        that.data.start -= 3;
                        that.data.end -= 3;
                        var html = "", year = that.data.yDate.year;
                        for (var i = that.data.start; i <= that.data.start + 2; i++) {
                            html += that._computedYearItemHtml(i, year);
                        }
                        
                        ul.insertAdjacentHTML("afterbegin", html);
                        for (var i = 0; i < 3; i++) {
                            ul.removeChild(ul.lastElementChild);
                        }
                    }
                    else if (transformY < -104) {
                        transformY += 52;
                        total -= 52;
                        that.data.startY -= 52;
                        that.data.start += 3;
                        var html = "", year = that.data.yDate.year;
                        for (var i = that.data.end; i <= that.data.end + 2; i++) {
                            html += that._computedYearItemHtml(i, year);
                        }
                        ul.insertAdjacentHTML("beforeend", html);
                        for (var i = 0; i < 3; i++) {
                            ul.removeChild(ul.firstElementChild);
                        }
                        that.data.end += 3;
                    }
                    yearContainer.style.transform = "translateY(" + transformY + "px)";
                    
                    that.data.backTransformY = transformY;
                }
                
            });
            this.addAnimation(animation);
        },
        selectDayHandler: function (ev) {
            var target = ev.target;
            if (target.classList.contains("li-item") && target.nodeName.toUpperCase() === "LI") {
                if (target.classList.contains("str-disabled-date-item")) return;
                this.data.selectDay = parseInt(target.textContent);
                this.attachDate();
                var selectDay = this.domList.monthContainer.querySelector(".selected");
                if (selectDay) selectDay.classList.remove("selected");
                ev.target.classList.add("selected");
                this.parent.staticPage.setDate();
            }
        },
        attachDate: function () {
            var data = this.data, yDate = data.yDate;
            yDate.year = data.selectYear;
            yDate.month = data.selectMonth;
            yDate.day = data.selectDay;
        },
        selectYearHandler: function (ev) {
            var target = ev.target, data = this.data, yDate = data.yDate;
            if (target.nodeName.toUpperCase() === "SPAN") {
                if (target.classList.contains("str-disabled-date-item")) return;
                var year = yDate.year, month = yDate.month, day = yDate.day;
                yDate.year = parseInt(target.textContent);
                data.selectYear = yDate.year;
                data.selectMonth = yDate.month;
                data.selectDay = yDate.day;
                this.domList.yearMonth.firstChild.nodeValue = yDate.toYearMonth();

                this.data.mode = "selectDay";
                this.domList.yearContainer.innerHTML = "";
                this.domList.header.classList.remove("select-year-mode");
                this.currentDom.innerHTML = this.computeHtml(yDate.getMonthDays());
                yDate.set(year, month, day);
            }
        },
        selectMonthHandler: function (ev) {
            if (this.data.mode === "selectDay") {
                this.data.mode = "selectYear";
                var html = "", year = this.data.yDate.year;
                for (var i = year - 10; i < year + 11; i++) {
                    html += this._computedYearItemHtml(i, year);
                }
                this.domList.yearContainer.innerHTML = "<ul>" + html + "</ul>";
                this.domList.header.classList.add("select-year-mode");
                this.domList.yearContainer.style.transform = "translateY(-52px)";
                this.data.transformY = -52;
                this.data.start = year - 10;
                this.data.end = year + 11;
            }
            else {
                this.data.mode = "selectDay";
                this.domList.yearContainer.innerHTML = "";
                this.domList.header.classList.remove("select-year-mode");
            }
        },
        init: function () {
            this.data.mode = "selectDay";
            this.domList.yearMonth.normalize();
            var monthContainer = this.domList.monthContainer;
            this.currentDom = monthContainer.querySelector(".current-container");
            this.backDom = monthContainer.querySelector(".back-container");

            this.computePrevNextStyle();
            this.parent.staticPage.activeSelect("date");
        },
        computePrevNextStyle: function () {
            if (!this.data.minDate && !this.data.maxDate) return;
            var data = this.data, selectYear = data.selectYear, selectMonth = data.selectMonth;
            var minDate = data.minDate, maxDate = data.maxDate;
            if (minDate) {
                if (selectYear == minDate.year && selectMonth == minDate.month) this.domList.previous.className = "ripple disabled";
                else this.domList.previous.className = "";
            }
            if (maxDate) {
                if (selectYear == maxDate.year && selectMonth == maxDate.month) this.domList.next.className = "ripple disabled";
                else this.domList.next.className = "";
            }
        },
        previousHandler: function (ev) {
            if (this.domList.previous.className === "ripple disabled") return;
            var data = this.data, yDate = this.data.yDate;
            var year = yDate.year, month = yDate.month, day = yDate.day;
            yDate.set(data.selectYear, data.selectMonth, data.selectDay);
            yDate.previousMonth();
            data.selectDay = yDate.day;
            data.selectMonth = yDate.month;
            data.selectYear = yDate.year;
            this.domList.yearMonth.firstChild.nodeValue = yDate.toYearMonth();
            this.backDom.innerHTML = this.computeHtml(yDate.getMonthDays(), year, month, day);
            this.domList.monthContainer.classList.add("date-turn-right");
            yDate.set(year, month, day);
            this.computePrevNextStyle();
        },
        nextHandler: function (ev) {
            if (this.domList.next.className === "ripple disabled") return;
            var data = this.data, yDate = this.data.yDate;
            var year = yDate.year, month = yDate.month, day = yDate.day;
            yDate.set(data.selectYear, data.selectMonth, data.selectDay);
            yDate.nextMonth();
            data.selectDay = yDate.day;
            data.selectMonth = yDate.month;
            data.selectYear = yDate.year;
            this.domList.yearMonth.firstChild.nodeValue = yDate.toYearMonth();
            this.backDom.innerHTML = this.computeHtml(yDate.getMonthDays(), year, month, day);
            this.domList.monthContainer.classList.add("date-turn-left");
            yDate.set(year, month, day);
            this.computePrevNextStyle();
        },
        animationEndHandler: function (ev) {
            if (ev.target !== this.domList.selectContainer) return;
            var monthContainer = this.domList.monthContainer, ulList = monthContainer.children;
            monthContainer.className = "month-container";
            var currentDom = this.currentDom, backDom = this.backDom;
            this.replaceDom(currentDom.classList, true);
            this.replaceDom(backDom.classList);
            this.currentDom = backDom;
            this.backDom = currentDom;
        },
        replaceDom: function (classList, isCurrent) {
            if (isCurrent) {
                classList.remove("current-container");
                classList.add("back-container");
            }
            else {
                classList.remove("back-container");
                classList.add("current-container");
            }
        },
        computeHtml: function (obj, year, month, day) {
            var tempHtml = "", now = new Date(),
                yDate = this.data.yDate, 
                data = this.data,
                year = year || data.selectYear, month = month || data.selectMonth, day = day || data.selectDay,
                tYear = now.getFullYear(), tMonth = now.getMonth() + 1, tDay = now.getDate();
            for (var i = 0; i < obj.prevNum; i++) {
                tempHtml += "<li></li>";
            }
            for (var i = 0; i < obj.num; i++) {
                var isDisabledClassStr = this._isInSelectDay(data.selectYear, data.selectMonth, i + 1);
                if (year == yDate.year && month == yDate.month && day - 1== i) {
                    tempHtml += '<li class="li-item' + isDisabledClassStr + ' selected">' + (i + 1) + '</li>';
                }
                else if (tYear == yDate.year && tMonth == yDate.month && tDay - 1== i) {
                    tempHtml += '<li class="li-item' + isDisabledClassStr + ' current">' + (i + 1) + '</li>';
                }
                else {
                    tempHtml += '<li class="li-item' + isDisabledClassStr + '">' + (i + 1) + '</li>';
                }
                
            }
            return tempHtml;
        },
        _isInSelectDay: function (year, month, day) {
            var minDate = this.data.minDate, maxDate = this.data.maxDate;
            if (!this.data.minDate && !this.data.maxDate) return "";
            if (!minDate) {
                if (maxDate.compare(year, month, day) > -1) return "";
                return " str-disabled-date-item";
            }
            if (!maxDate) {
                if (minDate.compare(year, month, day) < 1) return "";
                return " str-disabled-date-item";
            }

            if (maxDate.compare(year, month, day) > -1 && minDate.compare(year, month, day) < 1) return "";
            return " str-disabled-date-item";
        },
        render: function (next) {
            var data = this.data, parentDate = this.parent.data, 
                yDate = parentDate.yDate, minDate = parentDate.minDate, maxDate = parentDate.maxDate;
            data.selectYear = yDate.year;
            data.selectMonth = yDate.month;
            data.selectDay = yDate.day;
            data.yDate = yDate;
            data.minDate = minDate;
            data.maxDate = maxDate;
            data.selectYearMonth = data.yDate.toYearMonth();
            this.data.html = this.computeHtml(data.yDate.getMonthDays());
            this.fetch("./index.html", function (html) {
                next(this.renderHTML(html));
            })
        }
    })
});